﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client.Graphics;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Geometry;
using System.Configuration;
using System.Reflection;
using System.Diagnostics;
using System.IO;
using CPPEI.Coolzon.Common;

namespace CPPEI.Coolzon.UI.PetroleumDataPartLib
{
    /// <summary>
    /// GisMapPart.xaml 的交互逻辑
    /// </summary>
    [System.ComponentModel.DisplayName("Gis地图")]
    [XPartIcon("pack://application:,,,/CPPEI.Coolzon.UI.PetroleumDataPartLib;component/Images/PartIcons/GIS地图.png")]
    public partial class GisMapPart : ControlPart
    {
        #region 常量
        private const string MAPEXTENT = "mapextent";
        private const string MAPPOINT = "mappoint";
        private Envelope InitialEnvelope = null;
        private Dictionary<string, object> state = new Dictionary<string, object>();
        #endregion

        #region 字段
        private XMapEnvelope _viewStateEnvelope;
        private XMapPoint _viewStatePoint;
        private double? _oldResolution;
        //private double? _currentZoom;
        //private Envelope LastEnvelope;
        private string _sysName;
        private string _seletedGraphic;
        private IdentifyTask _identifyTask;
        private Dictionary<int, double> _lod = new Dictionary<int, double>();
        private List<int> _visibleLayerIDList = new List<int>();
        private bool _queryCompleted = true;
        #endregion

        #region XEvent
        /// <summary>
        /// 选择符号事件
        /// </summary>
        public static XEvent XEventOnSymbolSelected = XEventManager.Register(typeof(GisMapPart),
            "OnSymbolSelected",
            new XEventArgument("sender", typeof(Script.PartScriptObject)),
            new XEventArgument("data", typeof(Script.ArcGisScriptObject)));
        /// <summary>
        /// 地位分辨率事件
        /// </summary>
        public static XEvent XEventOnLocationResolution = XEventManager.Register(typeof(GisMapPart),
            "OnLocationResolution",
            new XEventArgument("sender", typeof(Script.PartScriptObject)),
            new XEventArgument("data", typeof(Script.ArcGisScriptObject)));
        /// <summary>
        /// 范围变更事件
        /// </summary>
        public static XEvent XEventOnExtendChanged = XEventManager.Register(typeof(GisMapPart),
            "OnExtendChanged",
            new XEventArgument("sender", typeof(Script.PartScriptObject)),
            new XEventArgument("data", typeof(Script.ArcGisScriptObject)));
        #endregion

        public GisMapPart()
        {
            InitializeComponent();
            _sysName = ConfigurationManager.AppSettings["SysName"];
        }
        public override void SaveViewState(CPPEI.Coolzon.ViewState.ViewState viewState)
        {
            Coolzon.ViewState.PartState partState = viewState.GetPartState(this.XFullName);
            if (partState == null)
            {
                partState = new Coolzon.ViewState.PartState(this.XFullName);
                viewState.AddPartState(partState);
            }

            #region save tab state
            XMapEnvelope envelope = new XMapEnvelope();
            envelope.XMax = map.Extent.XMax;
            envelope.XMin = map.Extent.XMin;
            envelope.YMax = map.Extent.YMax;
            envelope.YMin = map.Extent.YMin;

            XMapPoint point = new XMapPoint();
            point.X = map.Extent.GetCenter().X;
            point.Y = map.Extent.GetCenter().Y;

            partState.SetStringAndEncode(MAPEXTENT, Common.Serializer.XmlSerializer<XMapEnvelope>(envelope).ToString());
            partState.SetStringAndEncode(MAPPOINT, Common.Serializer.XmlSerializer<XMapPoint>(point).ToString());
            #endregion

            base.SaveViewState(viewState);
        }
        public override void LoadViewState(Coolzon.ViewState.ViewState viewState)
        {
            Coolzon.ViewState.PartState partState = viewState.GetPartState(this.XFullName);
            if (partState != null)
            {
                _hasViewState = true;

                #region load  state
                string extentString = partState.GetStringAndDecode(MAPEXTENT);
                string pointString = partState.GetStringAndDecode(MAPPOINT);

                if (!string.IsNullOrEmpty(extentString))
                {
                    _viewStateEnvelope =
                        Common.Serializer.XmlDeserialize<XMapEnvelope>(extentString);
                    if (map.Extent != null)
                    {
                        map.Extent.XMax = _viewStateEnvelope.XMax;
                        map.Extent.XMin = _viewStateEnvelope.XMin;
                        map.Extent.YMax = _viewStateEnvelope.YMax;
                        map.Extent.YMin = _viewStateEnvelope.YMin;
                    }
                }
                if (!string.IsNullOrEmpty(pointString))
                {
                    _viewStatePoint =
                        Common.Serializer.XmlDeserialize<XMapPoint>(pointString);
                    if (map.Extent != null)
                    {
                        map.Extent.GetCenter().X = _viewStatePoint.X;
                        map.Extent.GetCenter().Y = _viewStatePoint.Y;
                    }
                }
                #endregion
            }

            base.LoadViewState(viewState);
        }
        protected override void OnReset()
        {
            //map.Extent = InitialEnvelope;
            //if (state.ContainsKey("xlocation"))
            //{
            //    XInitialLocation = state["xlocation"].ToString();
            //    map.PanDuration = new TimeSpan(0);
            //    PanTo(XInitialLocation);
            //}
            map.ZoomTo(InitialEnvelope);
            //map.Extent = InitialEnvelope;
            base.OnReset();
        }
        protected override void OnActive(PartContext context)
        {
            InitMap();
            if (!string.IsNullOrWhiteSpace(XInitialLocation))
            {
                state.Add("xlocation", XInitialLocation);
            }
            base.OnActive(context);
        }
        /// <summary>
        /// 取消挂起的查询
        /// </summary>
        private void CancelIdentifyTask()
        {
            if (_identifyTask != null)
            {
                _identifyTask.CancelAsync();
                _identifyTask.ExecuteCompleted -= IdentifyTask_ExecuteCompleted;
                _identifyTask.Failed -= identifyTask_Failed;
                _identifyTask = null;
            }
        }
        protected override void OnDeactive(PartContext context)
        {
            if (XIsEnableInteraction)
            {
                //map.MouseUp += map_MouseUp;
                map.ExtentChanged -= map_ExtentChanged;
                map.ExtentChanging -= map_ExtentChanging;
                map.TouchDown -= map_TouchDown;
                map.MouseClick -= map_MouseClick;
            }

            map.IsEnabled = false;
            CancelIdentifyTask();
            ClearAllEvents(map);
            for (int i = 0; i < map.Layers.Count; i++)
            {
                if (map.Layers[i] is ESRI.ArcGIS.Client.FeatureLayer)
                {
                    ClearAllEvents(map.Layers[i] as ESRI.ArcGIS.Client.FeatureLayer);
                    (map.Layers[i] as ESRI.ArcGIS.Client.FeatureLayer).ClearGraphics();
                }
                else if (map.Layers[i] is ESRI.ArcGIS.Client.GraphicsLayer)
                {
                    (map.Layers[i] as ESRI.ArcGIS.Client.GraphicsLayer).ClearGraphics();
                }
                else if (map.Layers[i] is OGCMapLayer)
                {
                    ClearAllEvents(map.Layers[i] as OGCMapLayer);
                    (map.Layers[i]).Visible = false;
                    (map.Layers[i] as OGCMapLayer).Dispose();
                }
            }
            map.Layers.Clear();
            base.OnDeactive(context);
        }

        protected override void OnDestory()
        {
            if (XIsEnableInteraction)
            {
                //map.MouseUp += map_MouseUp;
                map.ExtentChanged -= map_ExtentChanged;
                map.ExtentChanging -= map_ExtentChanging;
                map.TouchDown -= map_TouchDown;
                map.MouseClick -= map_MouseClick;
            }

            map.IsEnabled = false;
            CancelIdentifyTask();
            ClearAllEvents(map);
            if (map == null || map.Layers.Count == 0) return;
            for (int i = 0; i < map.Layers.Count; i++)
            {
                if (map.Layers[i] is ESRI.ArcGIS.Client.FeatureLayer)
                {
                    ClearAllEvents(map.Layers[i] as ESRI.ArcGIS.Client.FeatureLayer);
                    (map.Layers[i] as ESRI.ArcGIS.Client.FeatureLayer).ClearGraphics();
                }
                else if (map.Layers[i] is ESRI.ArcGIS.Client.GraphicsLayer)
                {
                    (map.Layers[i] as ESRI.ArcGIS.Client.GraphicsLayer).ClearGraphics();
                }
                else if (map.Layers[i] is OGCMapLayer)
                {
                    ClearAllEvents(map.Layers[i] as OGCMapLayer);
                    (map.Layers[i]).Visible = false;
                    (map.Layers[i] as OGCMapLayer).Dispose();
                }
            }
            map.Layers.Clear();
            map = null;
            base.OnDestory();
        }

        /// <summary>
        /// 清除一个对象所有事件所挂钩的delegate
        /// </summary>
        /// <param name="objectHasEvents">有事件的对象</param>
        public static void ClearAllEvents(object objectHasEvents)
        {
            if (objectHasEvents == null)
            {
                return;
            }

            EventInfo[] events = objectHasEvents.GetType().GetEvents(
                BindingFlags.Public |
                BindingFlags.NonPublic |
                BindingFlags.Instance);

            if (events == null || events.Length < 1)
            {
                return;
            }

            for (int i = 0; i < events.Length; i++)
            {
                EventInfo ei = events[i];

                /********************************************************
                 * class的每个event都对应了一个同名的private的delegate类
                 * 型成员变量（这点可以用Reflector证实）。因为private成
                 * 员变量无法在基类中进行修改，所以为了能够拿到base 
                 * class中声明的事件，要从EventInfo的DeclaringType来获取
                 * event对应的成员变量的FieldInfo并进行修改
                 ********************************************************/
                FieldInfo fi =
                    ei.DeclaringType.GetField(ei.Name,
                                              BindingFlags.NonPublic |
                                              BindingFlags.Instance);

                if (fi != null)
                {
                    // 将event对应的字段设置成null即可清除所有挂钩在该event上的delegate
                    Delegate instanceDelegate = fi.GetValue(objectHasEvents) as Delegate;
                    if (instanceDelegate != null)
                    {
                        Delegate[] arrayDelegate = instanceDelegate.GetInvocationList();
                        if (arrayDelegate != null)
                        {
                            for (int index = 0; index < arrayDelegate.Length; index++)
                            {
                                try
                                {
                                    ei.RemoveEventHandler(objectHasEvents, arrayDelegate[index]);
                                    //Debug.WriteLine("remove delete:{0}", arrayDelegate[index]);
                                }
                                catch
                                {
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 地图初始化
        /// </summary>
        private void InitMap()
        {
            GraphicsLayer graphicsLayer = new GraphicsLayer();
            graphicsLayer.ID = "myg";
            map.Layers.Add(graphicsLayer);

            if (InitialEnvelope == null)
            {
                InitialEnvelope = map.Extent;
            }

            if (XIsEnableInteraction)
            {
                //map.MouseUp += map_MouseUp;
                map.ExtentChanged += map_ExtentChanged;
                map.ExtentChanging += map_ExtentChanging;
                map.TouchDown += map_TouchDown;
                map.MouseClick += map_MouseClick;
            }

            map.Width = XWidth;
            map.Height = XHeight;

        }
        void baseMap_Initialized(object sender, EventArgs e)
        {
            OGCMapLayer baseMap = sender as OGCMapLayer;
            if (this._lod.Count == 0)
            {
                for (int i = 0; i < baseMap.TileInfo.Lods.Length; i++)
                {
                    this._lod.Add(i, baseMap.TileInfo.Lods[i].Resolution);
                }
            }
        }

        void baseMap_TileLoaded(object sender, TiledLayer.TileLoadEventArgs e)
        {
            if (e.Error != null)
            {
                tbTip.Text = e.Error.Message;
            }
        }
        /// <summary>
        /// 地图点击事件
        /// </summary>
        /// <param name="clickPoint"></param>
        private void MapClick(MapPoint clickPoint)
        {
            if (string.IsNullOrWhiteSpace(XLayerIds)) return;
            ESRI.ArcGIS.Client.Tasks.IdentifyParameters identifyParams = new IdentifyParameters()
            {
                Geometry = clickPoint,
                MapExtent = map.Extent,
                Width = (int)map.ActualWidth,
                Height = (int)map.ActualHeight,
                LayerOption = LayerOption.visible,
                SpatialReference = map.SpatialReference,
                Tolerance = 25
            };
            string[] layerIds = XLayerIds.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < layerIds.Length; i++)
            {
                identifyParams.LayerIds.Add(Convert.ToInt32(layerIds[i]));
            }
            _queryCompleted = false;
            _identifyTask = new IdentifyTask(XBaseUrl);
            _identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
            _identifyTask.Failed += identifyTask_Failed;
            _identifyTask.ExecuteAsync(identifyParams);
        }

        void identifyTask_Failed(object sender, TaskFailedEventArgs e)
        {
            CPPEI.Coolzon.Common.Logger.WarningToTag("GisMapPart", "图层查询失败");
            _queryCompleted = true;
        }
        private void map_MouseClick(object sender, Map.MouseEventArgs e)
        {
            CPPEI.Coolzon.Common.Logger.InfoToTag("GisMapPart", "触发地图MouseClick事件,坐标{0}", e.MapPoint.ToString());
            if (_queryCompleted)
            {
                MapClick(e.MapPoint);
            }
        }
        void map_TouchDown(object sender, TouchEventArgs e)
        {
            CPPEI.Coolzon.Common.Logger.InfoToTag("GisMapPart", "触发地图TouchDown事件", map.ScreenToMap(e.GetTouchPoint(map).Position).ToString());
            if (_queryCompleted)
            {
                MapClick(map.ScreenToMap(e.GetTouchPoint(map).Position));
            }
        }

        public void ShowFeatures(List<IdentifyResult> results)
        {
            if (results != null && results.Count > 0)
            {
                foreach (IdentifyResult result in results)
                {
                    Graphic feature = result.Feature;

                    if (XIsSelect)
                    {
                        XMapPoint mapPoint = new XMapPoint()
                        {
                            X = feature.Geometry.Extent.GetCenter().X,
                            Y = feature.Geometry.Extent.GetCenter().Y,
                            WKID = feature.Geometry.Extent.SpatialReference.WKID,
                            WKT = feature.Geometry.Extent.SpatialReference.WKT
                        };
                        Select(mapPoint);

                        map.PanTo(feature.Geometry);
                    }

                    if (HasScriptEvent(XEventOnSymbolSelected.Name))
                    {
                        string attributesJson = Newtonsoft.Json.JsonConvert.SerializeObject(feature.Attributes);
                        Script.ArcGisScriptObject aso = new Script.ArcGisScriptObject();
                        aso.OnSymbolSelected(attributesJson, GetLevels(), IsSelected(feature), result.LayerId.ToString(), feature.Geometry.Extent.ToString());
                        this.InvokeScriptEvent(this.PartContext.ScriptEngine, XEventOnSymbolSelected.Name, this.GetScriptObj(), aso);
                    }
                    else if (HasScriptEvent(XEventOnLocationResolution.Name))
                    {
                        string attributesJson = Newtonsoft.Json.JsonConvert.SerializeObject(feature.Attributes);
                        Script.ArcGisScriptObject aso = new Script.ArcGisScriptObject();
                        aso.OnLocationResolution(feature.Geometry.Extent.ToString());
                        this.InvokeScriptEvent(this.PartContext.ScriptEngine, "OnLocationResolution", this.GetScriptObj(), aso);
                    }
                    break;
                }
            }
        }
        private string IsSelected(ESRI.ArcGIS.Client.Graphic grahic)
        {
            if (grahic.Attributes["OBJECTID"].ToString() == _seletedGraphic)
            {
                return bool.TrueString.ToLower();
            }
            else
            {
                _seletedGraphic = grahic.Attributes["OBJECTID"].ToString();
                return bool.FalseString.ToLower();
            }
        }
        /// <summary>
        /// 获取当前显示级别
        /// </summary>
        /// <returns></returns>
        private int GetLevels()
        {
            OGCMapLayer tileLayer = null;
            foreach (var layer in map.Layers)
            {
                if (layer is OGCMapLayer)
                {
                    tileLayer = layer as OGCMapLayer;
                    break;
                }
            }
            int currentLevel = 0;
            if (tileLayer != null)
            {
                for (; currentLevel < tileLayer.TileInfo.Lods.Length; currentLevel++)
                {
                    if (tileLayer.TileInfo.Lods[currentLevel].Resolution < map.Resolution)
                    {
                        currentLevel--;
                        break;
                    }
                }
            }
            return currentLevel;
        }
        private void SetVisibilityLayers()
        {
            ArcGISDynamicMapServiceLayer dynamicLayer = map.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;

            if (VisibleLayers != null)
            {
                string[] layerIds = VisibleLayers.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                _visibleLayerIDList = Array.ConvertAll<string, int>(layerIds, s => int.Parse(s)).ToList();
                dynamicLayer.VisibleLayers = _visibleLayerIDList.ToArray();
            }
        }
        /// <summary>
        /// 地图元素查询
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
        {
            if (args.IdentifyResults != null && args.IdentifyResults.Count > 0)
            {
                ShowFeatures(args.IdentifyResults);
                CPPEI.Coolzon.Common.Logger.InfoToTag("GisMapPart", "图层查询成功");
            }
            else
            {
                CPPEI.Coolzon.Common.Logger.WarningToTag("GisMapPart", "图层查询为空");
            }
            _queryCompleted = true;
        }
        void layer_UpdateFailed(object sender, ESRI.ArcGIS.Client.Tasks.TaskFailedEventArgs e)
        {
            if (e.Error != null)
            {
                tbTip.Text = e.Error.Message;
            }
        }
        void layer_UpdateCompleted(object sender, EventArgs e)
        {
            try
            {
                if (_viewStateEnvelope != null)
                {
                    ESRI.ArcGIS.Client.Geometry.Envelope envelope = new ESRI.ArcGIS.Client.Geometry.Envelope();
                    envelope.XMax = _viewStateEnvelope.XMax;
                    envelope.XMin = _viewStateEnvelope.XMin;
                    envelope.YMax = _viewStateEnvelope.YMax;
                    envelope.YMin = _viewStateEnvelope.YMin;
                    map.ZoomTo(envelope);
                }
                else
                {
                    PanTo(XInitialLocation);
                }
            }
            catch (Exception ex)
            {
                Common.Logger.ErrorToTag("GisMapPart", ex.Message);
            }

        }
        /// <summary>
        /// 地图定位
        /// </summary>
        /// <param name="graphicName"></param>
        private void PanTo(string graphicName)
        {
            ESRI.ArcGIS.Client.FeatureLayer layer = map.Layers[XLayerId] as ESRI.ArcGIS.Client.FeatureLayer;
            if (layer == null) return;
            GraphicCollection graphics = layer.Graphics;
            foreach (Graphic graphic in graphics)
            {
                if (graphic.Attributes.ContainsKey("NAME"))
                {
                    KeyValuePair<string, object> keyValue = graphic.Attributes.Where(p => p.Key.Equals("NAME")).First();
                    if (keyValue.Value.Equals(graphicName))
                    {
                        map.PanTo(graphic.Geometry);
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// 地图缩放
        /// </summary>
        /// <param name="zoomValue"></param>
        private void Zoom(double zoomValue)
        {
            map.Zoom(zoomValue);
        }
        void layer_InitializationFailed(object sender, EventArgs e)
        {
            ESRI.ArcGIS.Client.FeatureLayer layer = sender as ESRI.ArcGIS.Client.FeatureLayer;
            tbTip.Text = layer.InitializationFailure.Message;

            Common.Logger.ErrorToTag("GisMap", "业务地图加载失败" + layer.InitializationFailure.Message);
        }

        void map_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ESRI.ArcGIS.Client.Geometry.MapPoint mapPoint = map.Extent.GetCenter();
            XMapPoint mmapPoint = new XMapPoint();
            mmapPoint.X = mapPoint.X;
            mmapPoint.Y = mapPoint.Y;

            if (_sysName.Equals("Control"))
            {
                SendPartEvent<XMapPoint>(this.PartContext.Identity, "MapMove", mmapPoint);
            }
        }
        void map_ExtentChanging(object sender, ExtentEventArgs e)
        {
            //if (XMinResolution.HasValue && map.Resolution > XMinResolution)
            //{
            //    map.Extent = e.OldExtent;
            //}

        }
        /// <summary>
        /// 地图范围变更事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void map_ExtentChanged(object sender, ESRI.ArcGIS.Client.ExtentEventArgs e)
        {
            if (this.PartContext != null)
            {
                XMapEnvelope envelope = new XMapEnvelope();

                envelope.XMax = e.NewExtent.XMax;
                envelope.XMin = e.NewExtent.XMin;
                envelope.YMax = e.NewExtent.YMax;
                envelope.YMin = e.NewExtent.YMin;

                CPPEI.Coolzon.Common.Logger.InfoToTag("GisMapPart", "发送GisExtentChanged变更事件。");
                if (_sysName.Equals("Control"))
                {
                    SendPartEvent<XMapEnvelope>(this.PartContext.Identity, "ExtentChanged", envelope);
                }

                //if (InitialEnvelope == null)
                //{
                //    InitialEnvelope = new Envelope();
                //    InitialEnvelope = map.Extent;
                //}

                //if (_oldResolution.HasValue)
                //{
                //    if (map.Resolution > _oldResolution)
                //    {
                //        //缩放
                //        _currentZoom = _currentZoom / map.ZoomFactor;
                //    }
                //    else if (map.Resolution < _oldResolution)
                //    {
                //        //放大
                //        _currentZoom = _currentZoom * map.ZoomFactor;
                //    }
                //}
                //else
                //{
                //    _oldResolution = map.Resolution;
                //    _currentZoom = XZoomIn.HasValue ? XZoomIn.Value : 1;
                //}

                if (HasScriptEvent(XEventOnLocationResolution.Name))
                {
                    string attributesJson = Newtonsoft.Json.JsonConvert.SerializeObject(envelope);
                    Script.ArcGisScriptObject aso = new Script.ArcGisScriptObject();
                    aso.OnExtendChanged(attributesJson, GetLevels());
                    this.InvokeScriptEvent(this.PartContext.ScriptEngine, XEventOnLocationResolution.Name, this.GetScriptObj(), aso);
                }
            }
        }
        /// <summary>
        /// 设置地图显示级别
        /// </summary>
        /// <param name="level">显示级别</param>
        private void SetResolution(int level)
        {
            string[] points = this.XLocationPoint.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            MapPoint mapPoint = new MapPoint(Convert.ToDouble(points[0]), Convert.ToDouble(points[1]));
            this.map.PanDuration = TimeSpan.FromSeconds(0);
            this.map.PanTo(mapPoint);
            this.map.ZoomToResolution(this._lod[(int)level]);
        }
        /// <summary>
        /// 设置地图范围
        /// </summary>
        /// <param name="extent">XMax,XMin,YMax,YMin</param>
        private void SetExtent(string extent)
        {
            string[] strExtent = extent.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            Envelope envelop = new Envelope()
            {
                XMax = Convert.ToDouble(strExtent[0]),
                XMin = Convert.ToDouble(strExtent[1]),
                YMax = Convert.ToDouble(strExtent[2]),
                YMin = Convert.ToDouble(strExtent[3]),
            };
            map.Extent = envelop;
            InitialEnvelope = envelop;
        }
        private void Select(XMapPoint geo)
        {
            ESRI.ArcGIS.Client.Symbols.SimpleMarkerSymbol sms = new ESRI.ArcGIS.Client.Symbols.SimpleMarkerSymbol();
            sms.Color = XSelectBrush.Brush;
            sms.Size = XSelectSize;
            sms.Style = ESRI.ArcGIS.Client.Symbols.SimpleMarkerSymbol.SimpleMarkerStyle.Circle;

            Graphic graphic = new Graphic();
            graphic.Symbol = sms;

            MapPoint mapPoint = new MapPoint
            {
                X = geo.X,
                Y = geo.Y,
                SpatialReference = new SpatialReference { WKID = geo.WKID, WKT = geo.WKT }
            };

            graphic.Geometry = mapPoint;
            GraphicsLayer graphicsLayers;
            if (map.Layers.ToList().Any(p => p.ID == "myg"))
            {
                graphicsLayers = map.Layers["myg"] as GraphicsLayer;
                graphicsLayers.ClearGraphics();
            }
            else
            {
                graphicsLayers = new GraphicsLayer();
                graphicsLayers.ID = "myg";
            }
            graphicsLayers.Graphics.Add(graphic);
        }
        protected override void OnReceivePartEvent(string clientID, string eventName, byte[] eventData)
        {
            if (this.PartContext.Identity != clientID)
            {
                if (this.map.IsLoaded)
                {
                    if (eventName.Equals("ExtentChanged"))
                    {
                        CPPEI.Coolzon.Common.Logger.InfoToTag("GisMapPart", "地图变更事件接收成功.");
                        XMapEnvelope xEnvelope = (XMapEnvelope)Coolzon.Common.SerializeUtility.DeserializeFromBinary(eventData);
                        ESRI.ArcGIS.Client.Geometry.Envelope envelope = new ESRI.ArcGIS.Client.Geometry.Envelope();
                        envelope.XMax = xEnvelope.XMax;
                        envelope.XMin = xEnvelope.XMin;
                        envelope.YMax = xEnvelope.YMax;
                        envelope.YMin = xEnvelope.YMin;

                        this.map.ZoomTo(envelope);
                    }
                    else if (eventName.Equals("VisibilityChange"))
                    {
                        _visibleLayerIDList = (List<int>)Coolzon.Common.SerializeUtility.DeserializeFromBinary(eventData);
                        ArcGISDynamicMapServiceLayer dynamicLayer = map.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;
                        dynamicLayer.VisibleLayers = _visibleLayerIDList.ToArray();
                    }
                    else if (eventName.Equals("Select"))
                    {
                        Select((XMapPoint)Coolzon.Common.SerializeUtility.DeserializeFromBinary(eventData));
                    }
                }
            }
        }
        /// <summary>
        /// 清理指定类型图层
        /// </summary>
        /// <param name="type">图层类型</param>
        private void ClearMapLayer(Type type)
        {
            if (map != null && map.Layers != null)
            {
                for (int i = 0; i < map.Layers.Count; i++)
                {
                    if (map.Layers[i].GetType() == type)
                    {
                        if (map.Layers[i] is ESRI.ArcGIS.Client.FeatureLayer)
                        {
                            ClearAllEvents(map.Layers[i] as ESRI.ArcGIS.Client.FeatureLayer);
                            (map.Layers[i] as ESRI.ArcGIS.Client.FeatureLayer).ClearGraphics();
                        }
                        else if (map.Layers[i] is ESRI.ArcGIS.Client.GraphicsLayer)
                        {
                            (map.Layers[i] as ESRI.ArcGIS.Client.GraphicsLayer).ClearGraphics();
                        }
                        else if (map.Layers[i] is OGCMapLayer)
                        {
                            ClearAllEvents(map.Layers[i] as OGCMapLayer);
                            (map.Layers[i]).Visible = false;
                            (map.Layers[i] as OGCMapLayer).Dispose();
                        }
                        map.Layers.Remove(map.Layers[i]);
                        i--;
                    }
                }
            }
        }
        /// <summary>
        /// 添加地图
        /// </summary>
        private void AddBaseMap()
        {
            if (map.Layers.Count(p => p.GetType() == typeof(ArcGISDynamicMapServiceLayer)) != 0)
            {
                ClearMapLayer(typeof(ArcGISDynamicMapServiceLayer));
            }

            ArcGISDynamicMapServiceLayer dynamicLayer = new ArcGISDynamicMapServiceLayer();
            dynamicLayer.ID = "dynamicLayer";
            dynamicLayer.DisableClientCaching = true;
            dynamicLayer.Url = XBaseUrl;
            dynamicLayer.ImageFormat = ArcGISDynamicMapServiceLayer.RestImageFormat.PNG32;

            if (VisibleLayers != null)
            {
                string[] layerIds = VisibleLayers.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                _visibleLayerIDList = Array.ConvertAll<string, int>(layerIds, s => int.Parse(s)).ToList();
                dynamicLayer.VisibleLayers = _visibleLayerIDList.ToArray();
            }
            else
            {
                _visibleLayerIDList.Clear();
            }

            map.Layers.Add(dynamicLayer);

            dynamicLayer.Initialized += dynamicLayer_Initialized;
        }

        void dynamicLayer_Initialized(object sender, EventArgs e)
        {
            if (map == null)
            {
                return;
            }
            ArcGISDynamicMapServiceLayer dynamicLayer = map.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;


            if (!string.IsNullOrWhiteSpace(_sysName) && _sysName.Equals("Control"))
            {
                bdLayers.Visibility = Visibility.Visible;
                BindLayers(GetDefaultVisibleLayers());
            }
            dynamicLayer.Refresh();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private List<int> GetDefaultVisibleLayers()
        {
            List<int> visibleLayerIDList = new List<int>();
            ArcGISDynamicMapServiceLayer dynamicLayer = map.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;
            ESRI.ArcGIS.Client.LayerInfo[] layerInfoArray = dynamicLayer.Layers;
            if (layerInfoArray != null)
            {
                for (int index = 0; index < layerInfoArray.Length; index++)
                {
                    if ((layerInfoArray[index].SubLayerIds == null || layerInfoArray[index].SubLayerIds.Length == 0) &&
                        layerInfoArray[index].DefaultVisibility)
                        visibleLayerIDList.Add(index);
                }
            }
            else
            {
                Logger.ErrorToTag("GisMapPart", "map.Layers[\"dynamicLayer\"].Layers 是null对象。");
            }
            return visibleLayerIDList;
        }
        /// <summary>
        /// 绑定图层
        /// </summary>
        /// <param name="dynamicLayer"></param>
        private void BindLayers(List<int> visibleLayerIDList)
        {
            ArcGISDynamicMapServiceLayer dynamicLayer = map.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;
            if (dynamicLayer.Layers != null)
            {
                lbLayers.Items.Clear();
                foreach (LayerInfo layerInfo in dynamicLayer.Layers)
                {
                    CheckBox cbLayer = new CheckBox();
                    cbLayer.Content = layerInfo.ID + "." + layerInfo.Name;
                    cbLayer.FontSize = 22;
                    cbLayer.Tag = layerInfo;
                    if (visibleLayerIDList.Count == 0 || visibleLayerIDList.Contains(layerInfo.ID))
                    {
                        cbLayer.IsChecked = true;
                    }
                    cbLayer.Click += cbLayer_Click;
                    ListBoxItem item = new ListBoxItem();
                    item.Content = cbLayer;

                    lbLayers.Items.Add(item);
                }
            }
        }

        void cbLayer_Click(object sender, RoutedEventArgs e)
        {
            ArcGISDynamicMapServiceLayer layer = map.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;
            CheckBox cb = sender as CheckBox;
            LayerInfo layerInfo = cb.Tag as LayerInfo;
            if (cb.IsChecked.Value)
            {
                if (!_visibleLayerIDList.Contains(layerInfo.ID))
                {
                    _visibleLayerIDList.Add(layerInfo.ID);
                    layer.VisibleLayers = _visibleLayerIDList.ToArray();
                }
            }
            else
            {
                if (_visibleLayerIDList.Contains(layerInfo.ID))
                {
                    _visibleLayerIDList.Remove(layerInfo.ID);
                    layer.VisibleLayers = _visibleLayerIDList.ToArray();
                }
            }
            SendPartEvent<List<int>>(this.PartContext.Identity, "VisibilityChange", _visibleLayerIDList);
        }
        public bool _hasViewState { get; set; }

        public bool IsReceivePart { get; set; }
    }

    [Serializable]
    public class XMapEnvelope
    {
        public double XMax { get; set; }
        public double XMin { get; set; }
        public double YMax { get; set; }
        public double YMin { get; set; }
    }
    [Serializable]
    public class XMapPoint
    {
        public double X { get; set; }
        public double Y { get; set; }

        public int WKID { get; set; }
        public string WKT { get; set; }
    }
}
